/* Add base class variables to type information */

#ifndef MC_ADD_BASE_HPP
#define MC_ADD_BASE_HPP

#include <cassert>
#include <cstddef>
#include <typeinfo>

#include <memchart/demangle.hpp>
#include <memchart/rt_class_info.hpp>
#include <memchart/types.hpp>

namespace memchart
{
	template <typename Class, typename Base>
	struct add_base_impl
	{
		class member_info_impl : public rt_member_info
		{
			public:

				member_info_impl (const rt_member_info *base_m)
					: rt_member_info(
							demangle(typeid(Base).name()) + "::" + base_m->name,
							base_m->type
						),
					base_m(base_m)
				{ }

				string read (const void *p) const
				{
					assert(p != NULL);

					const Base *base = reinterpret_cast<const Class *>(p);

					return base_m->read(base);
				}

				bool is_writable () const
				{
					return base_m->is_writable();
				}

				void write (void *p, const string & val) const
				{
					assert(p != NULL);

					Base *base = reinterpret_cast<Class *>(p);

					base_m->write(base, val);
				}

				bool is_pointer () const
				{
					return base_m->is_pointer();
				}

				uintptr_t read_pointer (const void *p) const
				{
					assert(p != NULL);

					const Base *base = reinterpret_cast<const Class *>(p);

					return base_m->read_pointer(base);
				}

			private:

				const rt_member_info *base_m;
		};

		static void add (rt_member_vector & arr)
		{
			static vector<member_info_impl> members;

			const rt_class_info & base = Base::_memchart_class_info();

			members.reserve(base.count());

			/* Convert and add all base class members */
			for (size_t i = 0; i < base.count(); ++i)
			{
				members.push_back(member_info_impl(&base[i]));
				arr.push_back(&*members.rbegin());
			}
		}
	};


	template <typename Class, typename Base>
	inline void add_base (rt_member_vector & arr)
	{
		add_base_impl<Class, Base>::add(arr);
	}
}

#endif /* MC_ADD_BASE_HPP */
